#include "anillo.h"
#include "aed2_tests.h"

template<typename T>
string to_s(const Anillo<T>* a) {
	ostringstream os;
	os << *a;
	return os.str();
}

void AnilloNuevoEsVacio() {
	Anillo<int>* a = new Anillo<int>();
	ASSERT(a->esVacio());
	ASSERT_EQ(a->tamanio(), 0);
	delete a;
}

void AnilloUnitarioAlEliminarQuedaVacio() {
	Anillo<int>* a = new Anillo<int>();
	ASSERT(a->esVacio());
	ASSERT_EQ(a->tamanio(), 0);
    a->agregar(42);
	ASSERT(!a->esVacio());
	ASSERT_EQ(a->tamanio(), 1);
    a->eliminar(42);
	ASSERT(a->esVacio());
	ASSERT_EQ(a->tamanio(), 0);
	delete a;
}

void AnilloUnitarioDaSiguiente() {
	Anillo<int>* a = new Anillo<int>();
    a->agregar(42);
    ASSERT(!a->esVacio());
    ASSERT_EQ(a->tamanio(), 1);
    ASSERT_EQ(a->siguiente(), 42);
	delete a;
}

void MostrarAnilloVacio() {
	Anillo<int>* a = new Anillo<int>();
	ASSERT_EQ(to_s(a), "[]");
	delete a;
}

void MasNuevosQuedanPrimeros() {
   Anillo<int>* a = new Anillo<int>();
   a->agregar(42);
   a->agregar(20);
   a->agregar(10);
   ASSERT_EQ(a->actual(), 10);
   ASSERT_EQ(a->siguiente(), 20);
   ASSERT_EQ(a->siguiente(), 42);
   delete a;
}

void MuestroActualSiguienteYMarcado() {
   Anillo<int>* a = new Anillo<int>();
   a->agregar(42);
   a->marcar();
   a->agregar(20);
   a->marcar();
   a->agregar(10);
   ASSERT_EQ(a->actual(), 10);
   ASSERT_EQ(a->siguiente(), 20);
   ASSERT_EQ(a->siguiente(), 42);
   ASSERT_EQ(a->actual(), 42);
   ASSERT_EQ(a->marcado(), 20);
   delete a;
}

void ConstructorPorCopia() {
	Anillo<int>* a = new Anillo<int>();
	a->agregar(1);
	a->marcar();
	a->agregar(2);
	a->agregar(3);
	Anillo<int>* b = new Anillo<int>(*a);
	ASSERT_EQ(to_s(b), "[3, 2, 1*]");
	b->agregar(4);
	ASSERT_EQ(to_s(b), "[4, 3, 2, 1*]");
	ASSERT_EQ(to_s(a), "[3, 2, 1*]");
	b->eliminar(4);
	ASSERT_EQ(to_s(b), "[3, 2, 1*]");
	ASSERT_EQ(b->actual(), 3);
	ASSERT_EQ(to_s(a), "[3, 2, 1*]");
	delete a;
	ASSERT_EQ(to_s(b), "[3, 2, 1*]");
	b->marcar();
	ASSERT_EQ(to_s(b), "[3*, 2, 1]");
	delete b;
}

void ParaAdelanteYParaAtras() {
   Anillo<int>* a = new Anillo<int>();
   a->agregar(42);
   a->agregar(20);
   a->agregar(10);
   ASSERT_EQ(a->actual(), 10);
   ASSERT_EQ(a->siguiente(), 20);
   ASSERT_EQ(a->actual(), 20);
   ASSERT_EQ(a->siguiente(), 42);
   ASSERT_EQ(a->actual(), 42);
   a->retroceder();
   ASSERT_EQ(a->actual(), 20);
   a->retroceder();
   ASSERT_EQ(a->actual(), 10);
   delete a;
}

void IgualIgual() {
	Anillo<int>* a = new Anillo<int>();
	a->agregar(1);
	a->agregar(2);
	a->agregar(3);
    a->marcar();
	Anillo<int>* b = new Anillo<int>(*a);
	ASSERT_EQ(*a == *b , true);
	delete a;
	delete b;
}

void IgualIgual2() {
	Anillo<int>* a = new Anillo<int>();
	a->agregar(1);
	a->agregar(2);
	a->agregar(3);
    a->marcar();
	Anillo<int>* b = new Anillo<int>(*a);
	b->agregar(4);
	b->eliminar(4);
	ASSERT_EQ(*a == *b , true);
	delete a;
	delete b;
}

void IgualIgual3() {
    Anillo<int>* a = new Anillo<int>();
	a->agregar(1);
	a->marcar();
	a->agregar(2);
	a->marcar();
	a->agregar(3);
	Anillo<int>* b = new Anillo<int>();
    b->agregar(1);
    b->marcar();
	b->agregar(2);
	b->marcar();
	b->agregar(3);
    ASSERT_EQ(*a == *b , true);

	delete a;
	delete b;
}

void distintodistinto() {
	Anillo<int>* a = new Anillo<int>();
	a->agregar(1);
	a->agregar(2);
	a->agregar(3);
    a->marcar();
	Anillo<int>* b = new Anillo<int>(*a);
	b->agregar(4);
	ASSERT_EQ(*a == *b , false);
	delete a;
	delete b;
}

void distintodistinto2() {
	Anillo<int>* a = new Anillo<int>();
	a->agregar(1);
	a->agregar(2);
	a->agregar(3);
    a->marcar();
	Anillo<int>* b = new Anillo<int>(*a);
	b->agregar(4);
	b->marcar();
	ASSERT_EQ(*a == *b , false);
	delete a;
	delete b;
}

void distintodistinto3() {
    Anillo<int>* a = new Anillo<int>();
	a->agregar(1);
	a->marcar();
	a->agregar(2);
	a->marcar();
	a->agregar(3);
	Anillo<int>* b = new Anillo<int>();
    b->agregar(1);
    b->marcar();
	b->agregar(1);
	b->agregar(3);
    ASSERT_EQ(*a == *b , false);
	delete a;
	delete b;
}

int main(void) {
    RUN_TEST(AnilloNuevoEsVacio);
    RUN_TEST(AnilloUnitarioAlEliminarQuedaVacio);
    RUN_TEST(AnilloUnitarioDaSiguiente);
    RUN_TEST(MostrarAnilloVacio);
    RUN_TEST(MasNuevosQuedanPrimeros);
    RUN_TEST(MuestroActualSiguienteYMarcado);
    RUN_TEST(ConstructorPorCopia);
    RUN_TEST(ParaAdelanteYParaAtras);
    RUN_TEST(IgualIgual);
    RUN_TEST(IgualIgual2);
    RUN_TEST(IgualIgual3);
    RUN_TEST(distintodistinto);
    RUN_TEST(distintodistinto2);
    RUN_TEST(distintodistinto3);

    return 0;
}

